#include "XmlTools.h"

#include "Tools.h"

/**
 * 功能:
 *		跳到结点开始标签
 * 参数:
 *		char**		xml文本指针的指针
 * 返回值:
 *		-
 */
void XmlTools_ToTagStart(char** p)
{
	char *pStr = *p;
	if(!pStr)
	{
		return;
	}
	while (*pStr)
	{
		if(*pStr=='<')
		{
			break;
		}
		*pStr++;
	}
	*p = pStr;
}

/**
 * 功能:
 *		跳到结点结束标签
 * 参数:
 *		char**		xml文本指针的指针
 * 返回值:
 *		-
 */
void XmlTools_ToTagEnd(char** p)
{
	char *pStr = *p;
	if(!pStr)
	{
		return;
	}
	while (*pStr)
	{
		if(*pStr=='>')
		{
			break;
		}
		*pStr++;
	}
	*p = pStr;
}

/**
 * 功能:
 *		跳过格式字符串,格式字符包含:\r,\n,\t,空格
 * 参数:
 *		char**	pStr	xml文本指针的指针
 * 返回值:
 *		-
 */
void XmlTools_SkipFormatChar(char** p)
{
	char *pStr = *p;
	if(!pStr)
	{
		return;
	}
	while (*pStr)
	{
		if(*pStr!='\r'
		   && *pStr!='\n'
		   && *pStr!='\t'
		   && *pStr!=' ')
		{
			break;
		}
		*pStr++;
	}
	*p = pStr;
}

/**
 * 功能:
 *		转到下一个格式字符或标记字符位置包含:\r,\n,\t,空格,>,=,<,/
 * 参数:
 *		char**	pStr	xml文本指针的指针
 * 返回值:
 *		-
 */
void XmlTools_ToTagOrFormatChar(char** p)
{
	char *pStr = *p;
	while(*pStr)
	{
		if(*pStr=='\r'
		   ||*pStr=='\n'
		   ||*pStr=='\t'
		   ||*pStr==' '
		   ||*pStr=='>'
		   ||*pStr=='='
		   ||*pStr=='<'
		   ||*pStr=='/')
		{
			break;
		}
		pStr++;
	}
	*p = pStr;
}

/**
 * 功能:
 *		转到下一个属性变量标签位置
 * 参数:
 *		char**	pStr	xml文本指针的指针
 * 返回值:
 *		-
 */
void XmlTools_ToOptionValueTag(char** p)
{
	char *pStr = *p;
	while (*pStr)
	{
		if(*pStr=='\"'
		   ||*pStr=='\''
		   )
		{
			break;
		}
		*pStr++;
	}
	*p = pStr;
}


XML_NODE_OPTION* XmlTools_EncryptOption(char **p)
{
	XML_NODE_OPTION	*pNodeOption;
	char *pEnd;
	int nLen;
	char *pStart;
	
	pStart = *p;
	
	//跳过格式字符
	XmlTools_SkipFormatChar(&pStart);
	if (*pStart=='/' || *pStart=='?' || *pStart=='!' || *pStart=='>')
	{
		//XmlTools_ToTagEnd(pStart);
		//pStart++;
		//属性结束
		*p = pStart;
		return NULL;
	}
	
	//下一个格式字符或标记字符位置,取变量名
	pEnd = pStart;
	XmlTools_ToTagOrFormatChar(&pEnd);
	
	nLen = pEnd-pStart;
	
	pNodeOption = (XML_NODE_OPTION*)Tools_Malloc(sizeof(XML_NODE_OPTION	));
	pNodeOption->pName = (char*)Tools_Malloc(nLen+2);
	memcpy(pNodeOption->pName, pStart, nLen);
	pNodeOption->hash = ELFHash(pNodeOption->pName);
	
	//取变量值
	//pEnd = ++pStart;
	XmlTools_ToOptionValueTag(&pStart);
	pEnd = ++pStart;
	XmlTools_ToOptionValueTag(&pEnd);
	
	nLen = pEnd-pStart;
	
	pNodeOption->pValue = (char*)Tools_Malloc(nLen+1);
	memcpy(pNodeOption->pValue, pStart, nLen);
	
	pStart = ++pEnd;
	
	//解下一个属性
	pNodeOption->pNext = XmlTools_EncryptOption(&pStart);
	//pStart++;
	*p = pStart;
	return pNodeOption;
}


XML_NODE* XmlTools_Encrypt(char** p)
{
	XML_NODE *pNode;
	char *pEnd;
	int nLen;
	
	char *pStart;
	pStart = *p;
	
	if(!pStart || !*pStart)
	{
		*p = pStart;
		return NULL;
	}
	//跳过格式字符
	XmlTools_SkipFormatChar(&pStart);
	
	
	pNode = (XML_NODE*)Tools_Malloc(sizeof(XML_NODE));
	if (*pStart!='<')
	{
		//纯文本结点,找下一开始结点做为结束结点
		pNode->type = XML_NODE_TYPE_TEXT;
		pEnd = pStart+1;
		XmlTools_ToTagStart(&pEnd);
		//printf("\n node:text");
	}
	else
	{
		//查找标签tag结束位置
		char *p;
		p = pStart+1;
		if(*p=='?')
		{
			pNode->type = XML_NODE_TYPE_XMLTAG;
			++pStart;
			//printf("\n node:xml tag");
		}
		else if(*p=='!')
		{
			pNode->type = XML_NODE_TYPE_NOTE;
			++pStart;
			//printf("\n node:note");
		}
		else
		{
			pNode->type = XML_NODE_TYPE_NODE;
			//printf("\n node:node");
		}
		pEnd = ++pStart;
		XmlTools_ToTagOrFormatChar(&pEnd);
	}
	
	//如果是注释直接解析到注释结尾
	if(pNode->type == XML_NODE_TYPE_NOTE)
	{
		pEnd = strstr(pEnd, "-->");
		XmlTools_ToTagEnd(&pEnd);
	}
	
	//保存标签值
	nLen = pEnd-pStart;
	if(nLen<=0)
	{
		//</a>这类标签
		XmlTools_ToTagEnd(&pStart);
		pStart++;
		*p = pStart;
		Tools_Free(&pNode);
		return NULL;
	}
	pNode->pName = (char*)Tools_Malloc(nLen+2);
	memcpy(pNode->pName, pStart, nLen);
	pNode->hash = ELFHash(pNode->pName);
	
	if(pNode->type == XML_NODE_TYPE_TEXT)
	{
		//跳到下一开始标签处
		XmlTools_ToTagStart(&pStart);
	}
	else if(pNode->type == XML_NODE_TYPE_NODE
			||pNode->type == XML_NODE_TYPE_XMLTAG
			||pNode->type == XML_NODE_TYPE_NOTE)
	{
		//解析属性标签
		pStart = pEnd;
		pNode->pOption = XmlTools_EncryptOption(&pStart);
		
		if (pNode->type==XML_NODE_TYPE_XMLTAG) {
			
			pStart = strstr(pStart, "?")+1;

		}
		//跳过格式字符
		XmlTools_SkipFormatChar(&pStart);
		pEnd = pStart;
		pEnd++;
		XmlTools_SkipFormatChar(&pEnd);
		if((*pStart=='<' && *pEnd=='/')||(*pStart=='/' && *pEnd=='>'))
		{
			//结束标签;
			XmlTools_ToTagEnd(&pEnd);
			pStart = ++pEnd;
		}
		else
		{
			//wml,html 此处添加单一标签结束处理。
			if(pNode->type == XML_NODE_TYPE_XMLTAG
			   ||pNode->type == XML_NODE_TYPE_NOTE)
			{
				pStart = pEnd;
			}
			else
			{
				pStart++;
				//解释子结点
				pNode->pChildNode = XmlTools_Encrypt(&pStart);
				if(pNode->pChildNode)
				{
					pNode->pChildNode->pParentNode = pNode;
				}
			}
		}
		
	}
	
	//跳过格式字符
	XmlTools_SkipFormatChar(&pStart);
	pEnd = pStart;
	pEnd++;
	XmlTools_SkipFormatChar(&pEnd);
	if(*pStart=='<' && *pEnd=='/')
	{
		//结束标签;
		XmlTools_ToTagEnd(&pEnd);
		pStart = ++pEnd;
	}
	else
	{
		//解释兄弟结点
		pNode->pNextNode = XmlTools_Encrypt(&pStart);
		if(pNode->pNextNode)
		{
			pNode->pNextNode->pParentNode = pNode->pParentNode;
			pNode->pNextNode->pPrevNode = pNode;
		}
	}
	
	*p = pStart;
	return pNode;
}


void XmlTools_Free(XML_NODE* pNode)
{
	XML_NODE_OPTION *pTempOption;
	XML_NODE_OPTION *pTempOptionNext;
	if (!pNode)
	{
		return;
	}
	XmlTools_Free(pNode->pChildNode);//先释放子节点
	XmlTools_Free(pNode->pNextNode);//再释放兄弟节点
	pTempOption = pNode->pOption;
	while (pTempOption)//释放属性
	{
		pTempOptionNext = pTempOption->pNext;
		Tools_Free((void **)&pTempOption->pName);
		Tools_Free((void **)&pTempOption->pValue);
		Tools_Free((void **)&pTempOption);
		pTempOption = pTempOptionNext;
	}
	Tools_Free((void **)&pNode->pName);
	Tools_Free((void **)&pNode);
	pNode = NULL;
}


XML_NODE *XmlTools_GetLeafNode(XML_NODE *pNode, char *pText)
{
	XML_NODE *pTemp;
	u_int hash;
	if (!pNode)
	{
		return NULL;
	}
	pTemp = pNode;
	hash = ELFHash(pText);
	while (pTemp)
	{
		if (pTemp->hash==hash)
		{
			return pTemp;
		}
		pTemp = pTemp->pNextNode;
	}
	
	return NULL;
}


char* XmlTools_GetLeafText(XML_NODE *pNode)
{
	if (pNode && pNode->pChildNode)
	{
		return pNode->pChildNode->pName;
	}
	return NULL;
}


char* XmlTools_GetLeafNodeText(XML_NODE *pNode, char *pText)
{
	return XmlTools_GetLeafText(XmlTools_GetLeafNode(pNode, pText));
}


XML_NODE *XmlTools_GetLeafNodeNext(XML_NODE *pNode, char *pText)
{
	XML_NODE *pTemp;
	u_int hash;
	if (!pNode)
	{
		return NULL;
	}
	pTemp = pNode->pNextNode;
	hash = ELFHash(pText);
	while (pTemp)
	{
		if (pTemp->hash==hash)
		{
			return pTemp;
		}
		pTemp = pTemp->pNextNode;
	}
	
	return NULL;
}


XML_NODE *XmlTools_GetLeafNodeChild(XML_NODE *pNode, char *pText)
{
	XML_NODE *pTemp;
	u_int hash;
	if (!pNode)
	{
		return NULL;
	}
	pTemp = pNode->pChildNode;
	hash = ELFHash(pText);
	while (pTemp)
	{
		if (pTemp->hash==hash)
		{
			return pTemp;
		}
		pTemp = pTemp->pNextNode;
	}
	
	return NULL;
}

char* XmlTools_GetOptionValue(XML_NODE_OPTION *pOption, char *pName)
{
	
	u_int hash;
	if (!pOption)
	{
		return NULL;
	}
	
	hash = ELFHash(pName);
	while(pOption)
	{
		if (pOption->hash==hash)
		{
			return pOption->pValue;
		}
		pOption = pOption->pNext;
	}
	return NULL;
}

char* XmlTools_GetLeaf(char *pXml, char *pLeaf)
{
	char *pLeafStart;
	char *pLeafEnd;
	char *pStart;
	char *pEnd;
	char *pDes;
	int nDesLen;
	
	pStart = NULL;
	pEnd = NULL;
	
	pLeafStart = (char*)Tools_Malloc(strlen(pLeaf)+8);
	pLeafEnd = (char*)Tools_Malloc(strlen(pLeaf)+8);
	
	sprintf(pLeafStart, "<%s>", pLeaf);
	sprintf(pLeafEnd, "</%s>", pLeaf);
	
	//
	pStart = strstr(pXml, pLeafStart);
	//
	pEnd =  strstr(pXml, pLeafEnd);
	
	if(pStart==NULL || pEnd==NULL)
	{
		Tools_Free((void **)&pLeafStart);
		pLeafStart = NULL;
		Tools_Free((void **)&pLeafEnd);
		pLeafEnd = NULL;
		
		return NULL;
	}
	//
	nDesLen = pEnd-pStart-strlen(pLeafStart);
	if (nDesLen==0)
	{
		pDes = (char*)Tools_Malloc(2);
		memcpy(pDes, "", 1);
	}else
	{
		pDes = (char*)Tools_Malloc(nDesLen+2);
		memcpy(pDes, pStart+strlen(pLeafStart), nDesLen);
	}
	
	
	Tools_Free((void **)&pLeafStart);
	pLeafStart = NULL;
	Tools_Free((void **)&pLeafEnd);
	pLeafEnd = NULL;
	
	return pDes;
}



